/*
* CFile1.c
*
* Created: 2012-07-06 13:27:46
*  Author: Antrykot
*/


#include "main.h"
#include "lcd.h"
#include "sc-s.h"
#include "utils.h"
#include "trans-s.h"
#include "stdlib.h"
#include "../sc-k/SWLcd.h"

#if defined(MEDIA_PS) || defined(MEDIA_PD)
u16 pom_rh = 0;
u16 pom_pr = 0;
u16 pom_tm = 0;
#endif

u8 empty_buffer = 0;

u8 crc_data[10];
u8 crc_data_len;

u8 rk_addr = 0;
u16 rk_data = 0;
u8 rk_crc = 0;

u8 tk_addr = 0;
u16 tk_data = 0;
u8 tk_crc = 0;
u16 tk_pom = 0;
u8 tk_repeat = 0;

u8 tp_addr = 0;
u16 tp_data = 0;
u8 tp_crc = 0;
u8 tp_repeat = 0;

u8 rp_addr = 0;
u16 rp_data = 0;
u8 rp_crc = 0;
u16 rp_pom = 0;

u8 tk = 0;
u8 tp = 0;

u8 p_ack = 0;
u8 k_ack = 0;

u8 loop_cnt = 0;

u16 debug_data = 0;

u8 ksp_error = 0;

void setup_int()
{
	EICRA = 0 | (1 << ISC11) | (1 << ISC01);		// INT0 & INT1 falling edge
	
	TCCR0B = 0 | ( 1 << CS01);		// T0, prescale 8
	TIMSK0 |= ( 1 << TOIE0);		// interrupt T0 overflow
	
	
	
}

#ifndef MEDIA_CO2
void clk_p()
{
	PCK_L;
	WAITUS(120);
	PCK_H;
	WAITUS(120);
}
#else
void clk_p()
{
	PCK_L;
	WAITUS(12);
	PCK_H;
	WAITUS(12);
}

#endif

u8 get_8b_p()
{
	static u8 byte = 0;

	static i8 c = 0;
	
	byte = 0;
	c = 7;
	
	for (; c >= 0; c--)
	{
		clk_p();	// wait for falling edge
		PTX_HIG;
		if (PIND & (1 << 4))
		{
			byte |= ( 1 << c );
			PTX_LOW;
			PTX_HIG;

		}
		PTX_LOW;
	}
	WAITUS(120);
	return byte;
}

void set_8b_p(u8 data)
{
	static i8 c;
	c = 7;
	for (; c >= 0; c--)
	{
		if (data & (1 << c) )
		{
			PTX_HIG;
		}
		else
		{
			PTX_LOW;			// setup data
		}
		clk_p();		// wait for clk to became high again
	}
	//w_p_clk_l();
	WAITUS(120);
}

u8 trans_p()
{
	LG_ON;

	crc_data_len = 0;
	add_crc8(tp_addr);
	add_crc16(tp_data);
	tp_crc = crc8(crc_data,crc_data_len);
	
	PCK_L;			// get S to go into interrupt
	

	
	u8 c = 0;
	while (1)
	{
		if (!(PRXX))
		{
			WAITUS(100);
			break;
		}
		c++;
		if (c > 250)
		{
			PCK_H;
			return 0;		/// NO RESONSE FROM P - escape // 100ms (400us * 250)
		}
		
		WAITUS(400);
		
	#ifdef MEDIA_CO2		// sync mech

		if (c == 2)
		{
			if (tp_addr == P_ADDR_SYNC)
			{
				tp_addr = 0;			// drop SYNC, sine it was past time.
				PCK_H;
				return 0;
			}
		}
	#endif
	}



	
	PCK_H;
	
	
	set_8b_p(tp_addr);
	set_8b_p((tp_data & 0xFF00) >> 8);
	set_8b_p((tp_data & 0x00FF));
	set_8b_p(tp_crc);
	


	rp_addr = get_8b_p();

	rp_data = (get_8b_p() << 8);
	rp_data |= get_8b_p();
	rp_pom = (get_8b_p() << 8);
	rp_pom |= get_8b_p();
	rp_crc = get_8b_p();
	
	
	crc_data_len = 0;
	add_crc8(rp_addr);
	add_crc16(rp_data);
	add_crc16(rp_pom);
	
	u8 crc_r = crc8(crc_data,crc_data_len);
	if (crc_r == rp_crc)
	trp_ok = 1;
	else
	trp_ok = 0;
	
	clk_p();
	
	u8 was_not_ok = PRX;
	if (was_not_ok)		// if S didn't respond ok, transmision failed.	// high - failed to responde
	trp_ok = 0;
	
	
	PTX_HIG;
	PCK_H;
	
	LG_OFF;


	if (trp_ok)
	{
		LY_ON;

		meas = rp_pom;

		#if defined(MEDIA_PD) || defined(MEDIA_PS)
		u8 val = (rp_pom & 0xC000) >> 14;
		if ( val == 0x01)	// pressure
		{
			pom_pr = rp_pom & 0x3FFF;
		}
		if ( val == 0x02)	// humidity
		{
			pom_rh = rp_pom & 0x3FFF;
		}
		if ( val == 0x03)	// temperature
		{
			pom_tm = rp_pom & 0x3FFF;
		}
		#else

		if ((tk_pom < meas) || empty_buffer)		// -8.00%
		{
			#ifdef MEDIA_CH4IR
			if (((meas & 0xFF00) != 0xFF00 ))					// do not propagate CODES from P to K.
			{
				tk_pom = meas;
				tk_pom &= ~0x3000;	// delete 'minus' bits - in ch4ir it is indicating status, not minus.
				empty_buffer = 0;
			}
			if (meas == CODE_INIT)
			{
				tk_pom = 0xFFFF;
				empty_buffer = 1;
			}
			#else
			tk_pom = meas;
			empty_buffer = 0;
			
				
			#endif
		}

		#endif


		//tk_pom = meas;
		interpret_sp();
		if (!tp_repeat)
		{
			tp_data = 0;
			tp_addr = 0;
		}
		else
		{
			tp_repeat--;
		}

	}
	
	if (uout)
	{
		calc_dac_out();
		dac_set();
	}
	
	LG_OFF;
	return trp_ok;
}



inline void w_k_clk_l()
{
	while(KCK && !timeout);
}

inline void w_k_clk_h()
{
	while(!KCK && !timeout);
}



u8 crc()
{
	u8 crc8 = 0;
	for (u8 c = 0; c < crc_data_len; c++)
	{
		crc8 ^= crc_data[c];
		for(u8 i = 0; i < 8; i++)
		{
			if(crc8 & 0x80)
			crc8 = (crc8 << 1) ^ 0xE5;
			else
			//crc <<= 1;
			crc8 = (crc8 <<  1);
		}
		
	}
	return crc8;
}


u8 get_8b_k()
{
	u8 byte = 0;
	u8 val  = 0;
	for (i8 c = 7; c >= 0; c--)
	{
		w_k_clk_l();
		KTX_HIG;
		val = KRX;
		byte |= ( val << c );
		KTX_LOW;
		w_k_clk_h();
	}
	return byte;
}

void set_8b_k(u8 data)
{
	for (i8 c = 7; c >= 0; c--)
	{
		w_k_clk_l();
		if (data & (1 << c))
		KTX_HIG;
		else
		KTX_LOW;
		w_k_clk_h();
	}
}

void add_crc8(u8 byte)
{
	crc_data[crc_data_len] = byte;
	crc_data_len++;
}

void add_crc16(u16 word)
{
	crc_data[crc_data_len] = (word & 0xFF00) >> 8;
	crc_data_len ++;
	crc_data[crc_data_len] = (word & 0xFF) ;
	crc_data_len ++;
}


void trans_k()
{
	t0_cnt = 0;
	timeout = 0;
	T0START;


	#if defined(MEDIA_PS)



	switch(param_trans)
	{
		case 0x00:
		tk_pom = pom_pr & 0x3FFF;
		tk_pom |= 0x4000;
		break;
		case 0x01:
		tk_pom = pom_rh & 0x3FFF;
		tk_pom |= 0x8000;
		break;
		case 0x02:
		tk_pom = (pom_tm & 0x3FFF) ;
		tk_pom |= 0xC000;
		break;
		case 0x03:
		if (Ksp == 2)
		{
			param_trans = 0;
		}
	}
	if (Ksp == 2)
	{
		param_trans++;
		if (param_trans > 2)
		param_trans = 0;
	}
	#endif

	#if defined(MEDIA_PD)
	tk_pom = pom_pr & 0x3FFF ;
	tk_pom |= 0x4000;
	#endif
	
	static u8 add_param_cnt = 0;
	static u8 loophole = 0;			// if tk_addr is 0, insert voltages, but with "white places" (1 / 3 voltages)

	loophole++;
	if (!tk_addr && (!(loophole % 3)))		// do not insert voltage information in every frame
	{
		add_param_cnt++;
		
		switch(add_param_cnt)
		{
			case 1:
			tk_addr = K_ADDR_BATT_VOLT;
			tk_data = v_aku;
			break;
			case 2:
			tk_addr = K_ADDR_LINE_VOLT;
			tk_data = v_pow;
			break;
			case 3:
			tk_addr = K_ADDR_LINE_LOAD;
			tk_data = (v_pow - v_aku) / 0.0056;
			break;
			case 4:
			tk_addr = K_ADDR_PELI_VOLT;
			tk_data = v_dc;
			
			add_param_cnt = 0;
			break;
		}
		
	}
	
	if (!tk_addr)
	{
		check_input(1);		// force
	}
	
	crc_data_len = 0;
	add_crc8(tk_addr);
	add_crc16(tk_data);
	add_crc16(tk_pom);
	tk_crc = crc8(crc_data,crc_data_len);
	
	KTX_LOW;

	for (u8 c = 0; c < 200; c++)
	{
		if (KCK)		// wait for clock to became high again
		break;
		WAITUS(10);	// max 2ms
		
		if (c > 190)
		{
			KTX_HIG;
			T0STOP;
			return;		/// no response, quit transmision
		}
	}

	rk_addr = get_8b_k();
	rk_data = (get_8b_k() << 8);
	rk_data |= get_8b_k();
	rk_crc = get_8b_k();
	
	set_8b_k(tk_addr);
	set_8b_k((tk_data & 0xFF00) >> 8);
	set_8b_k((tk_data & 0x00FF));
	set_8b_k((tk_pom & 0xFF00) >> 8);
	set_8b_k((tk_pom & 0x00FF));
	set_8b_k(tk_crc);
	
	crc_data_len = 0;
	add_crc8(rk_addr);
	add_crc16(rk_data);
	
	u8 crc_c = crc8(crc_data,crc_data_len);
	w_k_clk_l();
	
	
	if (crc_c == rk_crc)
	{
		KTX_LOW;
		tk = 1;
		
		if (tk_repeat)
		{
			tk_repeat--;
		}
		else
		{
			tk_addr = 0;
			tk_data = 0;
		}
		//tk_pom = EMPTY_BUFFER;
		empty_buffer = 1;
	}
	else
	{
		KTX_HIG;
		LR_ON;
	}
	w_k_clk_h();
	WAITUS(150);
	
	KTX_HIG;
	LG_OFF;
	LR_OFF;
	
	static u8 l_blink = 0;
	l_blink++;
	if (l_blink > 15)
	{
		l_blink = 0;
		blink_led();
	}
	
	if (rk_addr == K_ADDR_SYNC)
	{
		tp_addr = P_ADDR_SYNC;
		tp_data = 0;
	}
	
	trans_p();


}

void interpret_sp()
{
	LY_OFF;
	switch (rp_addr)
	{
		case ADDR_VAKU:
		v_aku = rp_data ;
		break;
		case ADDR_VDC:
		v_dc = rp_data;
		break;
		case ADDR_VPOW:
		LY_ON;
		v_pow = rp_data ;
		break;
		case ADDR_TEMP:
		v_tmp = rp_data;
		break;
		case  P_ADDR_GETACT:
		debug_actref = rp_data;
		break;
		case  P_ADDR_GETREF:
		debug_actref = rp_data;
		break;
		case P_ADDR_GET_TCAL:
		debug_data = rp_data;
		break;
		case P_ADDR_GET_BETA:
		debug_data = rp_data;
		break;
		case P_ADDR_INCR_BETA:
		debug_data = rp_data;
		break;
		case P_ADDR_DECR_BETA:
		debug_data = rp_data;
		break;
	}
	
	
}

void interpret_sk()
{
	switch (rk_addr)
	{
		case K_ADDR_KSP:
		{
			ksp_error = 1;
			break;
		}
		
		case K_ADDR_CALFP:
		{
			kal_f = rk_data;
			break;
		}
		case  K_ADDR_DEBUG:
		{
			debug_data = rk_data;
			break;
		}
		case  K_ADDR_ALARMS:
		{
			u8 old_flag = awp_flags;
			
			if (!(rk_data & 0x01))
			{
				awp_flags |= AL1_FLAG;
				ALARM1_OFF;
			}
			else
			{
				awp_flags &= ~AL1_FLAG;
			}
			
			if (!(rk_data & 0x10))
			{
				awp_flags |= AL2_FLAG;
				ALARM2_OFF;
			}
			else
			{
				awp_flags &= ~AL2_FLAG;
			}

			if (awp_flags > old_flag)
			{
				LED_A_ON;
				WAITMS(35);
				LED_A_OFF;
			}
			awp_check();
			tk_data = check_input(0);
			tk_addr = K_ADDR_INPUT;
			
			break;
		}

		case K_ADDR_ACCEPT:
		{
			cal_wait_flag = 2;
			break;
		}
		
		case K_ADDR_DENY:
		{
			cal_wait_flag = 0;
			break;
		}
		
		case K_ADDR_CAL_STOP:
		{
			Pro = PRO_WORK;
			tp_addr = P_ADDR_RESET_DEFAULTS;
			tp_data = 0;
			lcd_clear();
			lcd_print(" KALIB. ");
			WAITMS(1500);
			lcd_home();
			lcd_print(" PRZERW.");
			WAITMS(1500);
			break;
		}
		case K_ADDR_NO_COMM:
		{
			if (Pro != PRO_WORK)
			break;
			lcd_home();
			lcd_print("BRAK KOM");
			awp_flags |= AL1_FLAG | AL2_FLAG;		// switch off alarms when KSP-3 and no communication.
			WAITMS(1000);
			break;
		}

		
	}
	
	
	if (time_cnt > 18000)		// about one hour
	{
		time_cnt = 0;
		time_cnt_h ++;
		
		write_word(EEP_WORK_TIME,time_cnt_h);
	}
}

u8 trp_ok = 0;





u16 time_cnt_h;
u16 time_cnt;